/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.gzchengguo.cn
 * 注意：
 * 本软件为www.gzchengguo.cn开发研制，未经购买不得商用
 * 购买后可获得全部源代码（禁止转卖、分享、上传到码云、github等开源平台）
 * 一经发现盗用、分享等行为，将追究法律责任，后果自负
 */
package link.chengguo.orangemall.modules.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import link.chengguo.orangemall.api.OrangeException;
import link.chengguo.orangemall.common.service.impl.BaseServiceImpl;
import link.chengguo.orangemall.common.utils.QueryHelpPlus;
import link.chengguo.orangemall.constant.ShopConstants;
import link.chengguo.orangemall.dozer.service.IGenerator;
import link.chengguo.orangemall.exception.BadRequestException;
import link.chengguo.orangemall.exception.ErrorRequestException;
import link.chengguo.orangemall.modules.category.domain.OrangeStoreCategory;
import link.chengguo.orangemall.modules.category.service.OrangeStoreCategoryService;
import link.chengguo.orangemall.modules.product.domain.OrangeStoreProduct;
import link.chengguo.orangemall.modules.product.domain.OrangeStoreProductAttrValue;
import link.chengguo.orangemall.modules.product.param.OrangeStoreProductQueryParam;
import link.chengguo.orangemall.modules.product.service.mapper.StoreProductMapper;
import link.chengguo.orangemall.modules.product.vo.ProductVo;
import link.chengguo.orangemall.modules.product.vo.OrangeStoreProductAttrQueryVo;
import link.chengguo.orangemall.modules.product.vo.OrangeStoreProductQueryVo;
import link.chengguo.orangemall.modules.product.vo.OrangeStoreProductReplyQueryVo;
import link.chengguo.orangemall.modules.shop.service.OrangeSystemStoreService;
import link.chengguo.orangemall.modules.template.domain.OrangeShippingTemplates;
import link.chengguo.orangemall.modules.template.service.OrangeShippingTemplatesService;
import link.chengguo.orangemall.modules.user.service.OrangeUserService;
import link.chengguo.orangemall.utils.FileUtil;
import link.chengguo.orangemall.utils.RedisUtil;
import link.chengguo.orangemall.utils.ShopKeyUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageInfo;
import link.chengguo.orangemall.enums.*;
import link.chengguo.orangemall.modules.product.service.*;
import link.chengguo.orangemall.modules.product.service.dto.*;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author chengguo
 * @date 2020-05-12
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class OrangeStoreProductServiceImpl extends BaseServiceImpl<StoreProductMapper, OrangeStoreProduct> implements OrangeStoreProductService {

    @Autowired
    private IGenerator generator;

    @Autowired
    private StoreProductMapper storeProductMapper;


    @Autowired
    private OrangeStoreCategoryService orangeStoreCategoryService;
    @Autowired
    private OrangeStoreProductAttrService orangeStoreProductAttrService;
    @Autowired
    private OrangeStoreProductAttrValueService orangeStoreProductAttrValueService;
    @Autowired
    private OrangeUserService userService;
    @Autowired
    private OrangeStoreProductReplyService replyService;
    @Autowired
    private OrangeStoreProductRelationService relationService;
    @Autowired
    private OrangeSystemStoreService systemStoreService;
    @Autowired
    private OrangeShippingTemplatesService shippingTemplatesService;
    @Autowired
    private OrangeStoreCategoryService categoryService;


    /**
     * 增加库存 减少销量
     * @param num 数量
     * @param productId 商品id
     * @param unique sku唯一值
     */
    @Override
    public void incProductStock(Integer num, Long productId, String unique) {
        if (StrUtil.isNotEmpty(unique)) {
            orangeStoreProductAttrService.incProductAttrStock(num, productId, unique);
        }
        storeProductMapper.incStockDecSales(num, productId);
    }

    /**
     * 减少库存与增加销量
     * @param num 数量
     * @param productId 商品id
     * @param unique sku
     */
    @Override
    public void decProductStock(int num, Long productId, String unique) {
        if (StrUtil.isNotEmpty(unique)) {
            orangeStoreProductAttrService.decProductAttrStock(num, productId, unique);
        }
        int res = storeProductMapper.decStockIncSales(num, productId);
        if (res == 0) {
            throw new OrangeException("商品库存不足");
        }
    }


    @Override
    public OrangeStoreProduct getProductInfo(int id) {
        QueryWrapper<OrangeStoreProduct> wrapper = new QueryWrapper<>();
        wrapper.eq("is_del", 0).eq("is_show", 1).eq("id", id);
        OrangeStoreProduct storeProduct = this.baseMapper.selectOne(wrapper);
        if (ObjectUtil.isNull(storeProduct)) {
            throw new ErrorRequestException("商品不存在或已下架");
        }

        return storeProduct;
    }


    /**
     * 获取单个商品
     * @param id 商品id
     * @return OrangeStoreProductQueryVo
     */
    @Override
    public OrangeStoreProductQueryVo getStoreProductById(Long id) {
        return generator.convert(this.baseMapper.selectById(id), OrangeStoreProductQueryVo.class);
    }


    /**
     * 返回普通商品库存
     * @param productId 商品id
     * @param unique sku唯一值
     * @return int
     */
    @Override
    public int getProductStock(Long productId, String unique) {
        OrangeStoreProductAttrValue storeProductAttrValue = orangeStoreProductAttrValueService
                .getOne(Wrappers.<OrangeStoreProductAttrValue>lambdaQuery()
                        .eq(OrangeStoreProductAttrValue::getUnique, unique)
                        .eq(OrangeStoreProductAttrValue::getProductId, productId));

        if (storeProductAttrValue == null) {
            return 0;
        }

        return storeProductAttrValue.getStock();

    }


    /**
     * 商品列表
     * @param productQueryParam OrangeStoreProductQueryParam
     * @return list
     */
    @Override
    public List<OrangeStoreProductQueryVo> getGoodsList(OrangeStoreProductQueryParam productQueryParam) {

        QueryWrapper<OrangeStoreProduct> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(OrangeStoreProduct::getIsShow, CommonEnum.SHOW_STATUS_1.getValue());

        //分类搜索
        if (StrUtil.isNotBlank(productQueryParam.getSid()) &&
                !ShopConstants.ORANGEMALL_ZERO.equals(productQueryParam.getSid())) {
            List<OrangeStoreCategory> list = categoryService.list(new QueryWrapper<OrangeStoreCategory>().eq("pid", productQueryParam.getSid()));
            if (list != null && list.size() > 0) {
                wrapper.lambda().and(x -> {
                    for (OrangeStoreCategory category : list) {
                        x.like(OrangeStoreProduct::getCateId, "," + category.getId() + ",").or();
                    }
                });
            } else {
                wrapper.lambda().like(OrangeStoreProduct::getCateId, "," + productQueryParam.getSid() + ",");
            }
        }
        //关键字搜索
        if (StrUtil.isNotEmpty(productQueryParam.getKeyword())) {
            wrapper.lambda().like(OrangeStoreProduct::getStoreName, productQueryParam.getKeyword());
        }

        //新品搜索
        if (StrUtil.isNotBlank(productQueryParam.getNews()) &&
                !ShopConstants.ORANGEMALL_ZERO.equals(productQueryParam.getNews())) {
            wrapper.lambda().eq(OrangeStoreProduct::getIsNew, ShopCommonEnum.IS_NEW_1.getValue());
        }

        //销量排序
        if (SortEnum.DESC.getValue().equals(productQueryParam.getSalesOrder())) {
            wrapper.lambda().orderByDesc(OrangeStoreProduct::getSales);
        } else if (SortEnum.ASC.getValue().equals(productQueryParam.getSalesOrder())) {
            wrapper.lambda().orderByAsc(OrangeStoreProduct::getSales);
        }

        //价格排序
        if (SortEnum.DESC.getValue().equals(productQueryParam.getPriceOrder())) {
            wrapper.lambda().orderByDesc(OrangeStoreProduct::getPrice);
        } else if (SortEnum.ASC.getValue().equals(productQueryParam.getPriceOrder())) {
            wrapper.lambda().orderByAsc(OrangeStoreProduct::getPrice);
        }

        wrapper.lambda().orderByDesc(OrangeStoreProduct::getSort);

        Page<OrangeStoreProduct> pageModel = new Page<>(productQueryParam.getPage(),
                productQueryParam.getLimit());

        IPage<OrangeStoreProduct> pageList = storeProductMapper.selectPage(pageModel, wrapper);
        sumSalesFicti(pageList.getRecords());
        List<OrangeStoreProductQueryVo> list = generator.convert(pageList.getRecords(), OrangeStoreProductQueryVo.class);

        return list;
    }

    /**
     * 商品详情
     * @param id 商品id
     * @param uid 用户id
     * @param latitude 纬度
     * @param longitude 经度
     * @return ProductVo
     */
    @Override
    public ProductVo goodsDetail(Long id, Long uid, String latitude, String longitude) {
        QueryWrapper<OrangeStoreProduct> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(OrangeStoreProduct::getIsShow, ShopCommonEnum.SHOW_1.getValue())
                .eq(OrangeStoreProduct::getId, id);
        OrangeStoreProduct storeProduct = storeProductMapper.selectOne(wrapper);
        if (ObjectUtil.isNull(storeProduct)) {
            throw new ErrorRequestException("商品不存在或已下架");
        }

        //获取商品sku
        Map<String, Object> returnMap = orangeStoreProductAttrService.getProductAttrDetail(id);
        ProductVo productVo = new ProductVo();
        OrangeStoreProductQueryVo storeProductQueryVo = generator.convert(storeProduct, OrangeStoreProductQueryVo.class);
        //设置虚拟销量
        storeProductQueryVo.setSales(storeProductQueryVo.getSales() + storeProduct.getFicti());
        //设置VIP价格
        Map<String, OrangeStoreProductAttrValue> productValue = (Map<String, OrangeStoreProductAttrValue>) returnMap.get("productValue");
        Iterator<Map.Entry<String, OrangeStoreProductAttrValue>> iterator = productValue.entrySet().iterator();
        OrangeStoreProductAttrValue productAttrValue = iterator.next().getValue();
        while (iterator.hasNext()) {
            OrangeStoreProductAttrValue value = iterator.next().getValue();
            if (productAttrValue.getId() > value.getId()) {
                productAttrValue = value;
            }
        }
        double vipPrice = userService.setLevelPrice(productAttrValue, uid);
        storeProductQueryVo.setVipPrice(BigDecimal.valueOf(vipPrice).setScale(2, BigDecimal.ROUND_CEILING));

        //收藏
        boolean isCollect = relationService.isProductRelation(id, uid);
        storeProductQueryVo.setUserCollect(isCollect);

        //总条数
        int totalCount = replyService.productReplyCount(id);
        productVo.setReplyCount(totalCount);

        //评价
        OrangeStoreProductReplyQueryVo storeProductReplyQueryVo = replyService.getReply(id);
        productVo.setReply(storeProductReplyQueryVo);

        //好评比例
        String replyPer = replyService.replyPer(id);
        productVo.setReplyChance(replyPer);

        //获取运费模板名称
        String storeFreePostage = RedisUtil.get("store_free_postage");
        String tempName = "";
        if (StrUtil.isBlank(storeFreePostage)
                || !NumberUtil.isNumber(storeFreePostage)
                || Integer.valueOf(storeFreePostage) == 0) {
            tempName = "全国包邮";
        } else {
            OrangeShippingTemplates shippingTemplates = shippingTemplatesService.getById(storeProduct.getTempId());
            if (ObjectUtil.isNotNull(shippingTemplates)) {
                tempName = shippingTemplates.getName();
            } else {
                throw new BadRequestException("请配置运费模板");
            }

        }
        productVo.setTempName(tempName);

        //设置商品相关信息
        productVo.setStoreInfo(storeProductQueryVo);
        productVo.setProductAttr((List<OrangeStoreProductAttrQueryVo>) returnMap.get("productAttr"));
        productVo.setProductValue((Map<String, OrangeStoreProductAttrValue>) returnMap.get("productValue"));


        //门店
        productVo.setSystemStore(systemStoreService.getStoreInfo(latitude, longitude));
        productVo.setMapKey(RedisUtil.get(ShopKeyUtils.getTengXunMapKey()));

        return productVo;
    }


    /**
     * 商品列表
     * @param page 页码
     * @param limit 条数
     * @param order ProductEnum
     * @return List
     */
    @Override
    public List<OrangeStoreProductQueryVo> getList(int page, int limit, int order) {

        QueryWrapper<OrangeStoreProduct> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(OrangeStoreProduct::getIsShow, ShopCommonEnum.SHOW_1.getValue())
                .orderByDesc(OrangeStoreProduct::getSort);

        // order
        switch (ProductEnum.toType(order)) {
            case TYPE_1:
                wrapper.lambda().eq(OrangeStoreProduct::getIsBest,
                        ShopCommonEnum.IS_STATUS_1.getValue()); //精品推荐
                break;
            case TYPE_3:
                wrapper.lambda().eq(OrangeStoreProduct::getIsNew,
                        ShopCommonEnum.IS_STATUS_1.getValue());// 首发新品
                break;
            case TYPE_4:
                wrapper.lambda().eq(OrangeStoreProduct::getIsBenefit,
                        ShopCommonEnum.IS_STATUS_1.getValue()); // 猜你喜欢
                break;
            case TYPE_2:
                wrapper.lambda().eq(OrangeStoreProduct::getIsHot,
                        ShopCommonEnum.IS_STATUS_1.getValue());// 热门榜单
                break;
            default:

        }
        Page<OrangeStoreProduct> pageModel = new Page<>(page, limit);

        IPage<OrangeStoreProduct> pageList = storeProductMapper.selectPage(pageModel, wrapper);
        sumSalesFicti(pageList.getRecords());

        return generator.convert(pageList.getRecords(), OrangeStoreProductQueryVo.class);
    }

    /**设置销量:真实销量+虚拟销量**/
    private void sumSalesFicti(List<OrangeStoreProduct> list) {
        for(OrangeStoreProduct orangeStoreProduct:list){
            int temp = orangeStoreProduct.getFicti() + orangeStoreProduct.getSales();
            orangeStoreProduct.setSales(temp);
        }
    }


    //============ 分割线================//


    @Override
    public Map<String, Object> queryAll(OrangeStoreProductQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<OrangeStoreProduct> page = new PageInfo<>(queryAll(criteria));
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", generator.convert(page.getList(), OrangeStoreProductDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }


    @Override
    public List<OrangeStoreProduct> queryAll(OrangeStoreProductQueryCriteria criteria) {
        List<OrangeStoreProduct> orangeStoreProductList = baseMapper.selectList(QueryHelpPlus.getPredicate(OrangeStoreProduct.class, criteria));
        orangeStoreProductList.forEach(orangeStoreProduct -> {
            orangeStoreProduct.setStoreCategory((List<OrangeStoreCategory>) orangeStoreCategoryService.listByIds(Arrays.asList(orangeStoreProduct.getCateId().split(","))));
        });
        return orangeStoreProductList;
    }


    @Override
    public void download(List<OrangeStoreProductDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (OrangeStoreProductDto orangeStoreProduct : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("商户Id(0为总后台管理员创建,不为0的时候是商户后台创建)", orangeStoreProduct.getMerId());
            map.put("商品图片", orangeStoreProduct.getImage());
            map.put("轮播图", orangeStoreProduct.getSliderImage());
            map.put("商品名称", orangeStoreProduct.getStoreName());
            map.put("商品简介", orangeStoreProduct.getStoreInfo());
            map.put("关键字", orangeStoreProduct.getKeyword());
            map.put("产品条码（一维码）", orangeStoreProduct.getBarCode());
            map.put("分类id", orangeStoreProduct.getCateId());
            map.put("商品价格", orangeStoreProduct.getPrice());
            map.put("会员价格", orangeStoreProduct.getVipPrice());
            map.put("市场价", orangeStoreProduct.getOtPrice());
            map.put("邮费", orangeStoreProduct.getPostage());
            map.put("单位名", orangeStoreProduct.getUnitName());
            map.put("排序", orangeStoreProduct.getSort());
            map.put("销量", orangeStoreProduct.getSales());
            map.put("库存", orangeStoreProduct.getStock());
            map.put("状态（0：未上架，1：上架）", orangeStoreProduct.getIsShow());
            map.put("是否热卖", orangeStoreProduct.getIsHot());
            map.put("是否优惠", orangeStoreProduct.getIsBenefit());
            map.put("是否精品", orangeStoreProduct.getIsBest());
            map.put("是否新品", orangeStoreProduct.getIsNew());
            map.put("产品描述", orangeStoreProduct.getDescription());
            map.put("添加时间", orangeStoreProduct.getAddTime());
            map.put("是否包邮", orangeStoreProduct.getIsPostage());
            map.put("是否删除", orangeStoreProduct.getIsDel());
            map.put("商户是否代理 0不可代理1可代理", orangeStoreProduct.getMerUse());
            map.put("获得积分", orangeStoreProduct.getGiveIntegral());
            map.put("成本价", orangeStoreProduct.getCost());
            map.put("秒杀状态 0 未开启 1已开启", orangeStoreProduct.getIsSeckill());
            map.put("砍价状态 0未开启 1开启", orangeStoreProduct.getIsBargain());
            map.put("是否优品推荐", orangeStoreProduct.getIsGood());
            map.put("虚拟销量", orangeStoreProduct.getFicti());
            map.put("浏览量", orangeStoreProduct.getBrowse());
            map.put("产品二维码地址(用户小程序海报)", orangeStoreProduct.getCodePath());
            map.put("淘宝京东1688类型", orangeStoreProduct.getSoureLink());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }


    /**
     * 商品上架下架
     * @param id 商品id
     * @param status  ShopCommonEnum
     */
    @Override
    public void onSale(Long id, Integer status) {
        if (ShopCommonEnum.SHOW_1.getValue().equals(status)) {
            status = ShopCommonEnum.SHOW_0.getValue();
        } else {
            status = ShopCommonEnum.SHOW_1.getValue();
        }
        storeProductMapper.updateOnsale(status, id);
    }


    /**
     * 新增/保存商品
     * @param storeProductDto 商品
     */
    @Override
    public void insertAndEditOrangeStoreProduct(StoreProductDto storeProductDto) {

        ProductResultDto resultDTO = this.computedProduct(storeProductDto.getAttrs());

        //添加商品
        OrangeStoreProduct orangeStoreProduct = new OrangeStoreProduct();
        BeanUtil.copyProperties(storeProductDto, orangeStoreProduct, "sliderImage");
        if (storeProductDto.getSliderImage().isEmpty()) {
            throw new OrangeException("请上传轮播图");
        }

        orangeStoreProduct.setPrice(BigDecimal.valueOf(resultDTO.getMinPrice()));
        orangeStoreProduct.setOtPrice(BigDecimal.valueOf(resultDTO.getMinOtPrice()));
        orangeStoreProduct.setCost(BigDecimal.valueOf(resultDTO.getMinCost()));
        orangeStoreProduct.setStock(resultDTO.getStock());
        orangeStoreProduct.setSliderImage(String.join(",", storeProductDto.getSliderImage()));


        this.saveOrUpdate(orangeStoreProduct);

        //属性处理
        //处理单sKu
        if (SpecTypeEnum.TYPE_0.getValue().equals(storeProductDto.getSpecType())) {
            FromatDetailDto fromatDetailDto = FromatDetailDto.builder()
                    .value("规格")
                    .detailValue("")
                    .attrHidden("")
                    .detail(ListUtil.toList("默认"))
                    .build();
            List<Map<String, Object>> attrs = storeProductDto.getAttrs();
            Map<String, Object> map = attrs.get(0);
            map.put("value1", "规格");
            map.put("detail", MapUtil.of(new String[][]{
                    {"规格", "默认"}
            }));
            orangeStoreProductAttrService.insertOrangeStoreProductAttr(ListUtil.toList(fromatDetailDto),
                    ListUtil.toList(map), orangeStoreProduct.getId());
        } else {
            orangeStoreProductAttrService.insertOrangeStoreProductAttr(storeProductDto.getItems(),
                    storeProductDto.getAttrs(), orangeStoreProduct.getId());
        }


    }


    /**
     * 获取生成的属性
     * @param id 商品id
     * @param jsonStr jsonStr
     * @return map
     */
    @Override
    public Map<String, Object> getFormatAttr(Long id, String jsonStr) {
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        Map<String, Object> resultMap = new LinkedHashMap<>(3);

        if (jsonObject == null || jsonObject.get("attrs") == null || jsonObject.getJSONArray("attrs").isEmpty()) {
            resultMap.put("attr", new ArrayList<>());
            resultMap.put("value", new ArrayList<>());
            resultMap.put("header", new ArrayList<>());
            return resultMap;
        }


        List<FromatDetailDto> fromatDetailDTOList = JSON.parseArray(jsonObject.get("attrs").toString(),
                FromatDetailDto.class);

        //fromatDetailDTOList
        DetailDto detailDto = this.attrFormat(fromatDetailDTOList);

        List<Map<String, Object>> headerMapList = null;
        List<Map<String, Object>> valueMapList = new ArrayList<>();
        String align = "center";
        Map<String, Object> headerMap = new LinkedHashMap<>();
        for (Map<String, Map<String, String>> map : detailDto.getRes()) {
            Map<String, String> detail = map.get("detail");
            String[] detailArr = detail.values().toArray(new String[]{});
            Arrays.sort(detailArr);

            String sku = String.join(",", detailArr);

            Map<String, Object> valueMap = new LinkedHashMap<>();

            List<String> detailKeys =
                    detail.entrySet()
                            .stream()
                            .map(Map.Entry::getKey)
                            .collect(Collectors.toList());

            int i = 0;
            headerMapList = new ArrayList<>();
            for (String title : detailKeys) {
                headerMap.put("title", title);
                headerMap.put("minWidth", "130");
                headerMap.put("align", align);
                headerMap.put("key", "value" + (i + 1));
                headerMap.put("slot", "value" + (i + 1));
                headerMapList.add(ObjectUtil.clone(headerMap));
                i++;
            }

            String[] detailValues = detail.values().toArray(new String[]{});
            for (int j = 0; j < detailValues.length; j++) {
                String key = "value" + (j + 1);
                valueMap.put(key, detailValues[j]);
            }

            valueMap.put("detail", detail);
            valueMap.put("pic", "");
            valueMap.put("price", 0);
            valueMap.put("cost", 0);
            valueMap.put("ot_price", 0);
            valueMap.put("stock", 0);
            valueMap.put("bar_code", "");
            valueMap.put("weight", 0);
            valueMap.put("volume", 0);
            valueMap.put("brokerage", 0);
            valueMap.put("brokerage_two", 0);
            if (id > 0) {
                OrangeStoreProductAttrValue storeProductAttrValue = orangeStoreProductAttrValueService
                        .getOne(Wrappers.<OrangeStoreProductAttrValue>lambdaQuery()
                                .eq(OrangeStoreProductAttrValue::getProductId, id)
                                .eq(OrangeStoreProductAttrValue::getSku, sku));
                if (storeProductAttrValue != null) {
                    valueMap.put("pic", storeProductAttrValue.getImage());
                    valueMap.put("uniqueId", storeProductAttrValue.getUnique());
                    valueMap.put("price", storeProductAttrValue.getPrice());
                    valueMap.put("cost", storeProductAttrValue.getCost());
                    valueMap.put("ot_price", storeProductAttrValue.getOtPrice());
                    valueMap.put("stock", storeProductAttrValue.getStock());
                    valueMap.put("vipPrice", storeProductAttrValue.getVipPrice());
                    valueMap.put("bar_code", storeProductAttrValue.getBarCode());
                    valueMap.put("weight", storeProductAttrValue.getWeight());
                    valueMap.put("volume", storeProductAttrValue.getVolume());
                    valueMap.put("brokerage", storeProductAttrValue.getBrokerage());
                    valueMap.put("brokerage_two", storeProductAttrValue.getBrokerageTwo());
                }
            }

            valueMapList.add(ObjectUtil.clone(valueMap));

        }

        this.addMap(headerMap, headerMapList, align);


        resultMap.put("attr", fromatDetailDTOList);
        resultMap.put("value", valueMapList);
        resultMap.put("header", headerMapList);

        return resultMap;
    }


    /**
     * 计算产品数据
     * @param attrs attrs
     * @return ProductResultDto
     */
    private ProductResultDto computedProduct(List<Map<String, Object>> attrs) {
        //取最小价格
        Double minPrice = ListMapToListBean(attrs)
                .stream()
                .map(ProductFormatDto::getPrice)
                .min(Comparator.naturalOrder())
                .orElse(0d);

        Double minOtPrice = ListMapToListBean(attrs)
                .stream()
                .map(ProductFormatDto::getOtPrice)
                .min(Comparator.naturalOrder())
                .orElse(0d);

        Double minCost = ListMapToListBean(attrs)
                .stream()
                .map(ProductFormatDto::getCost)
                .min(Comparator.naturalOrder())
                .orElse(0d);
        //计算库存
        Integer stock = ListMapToListBean(attrs)
                .stream()
                .map(ProductFormatDto::getStock)
                .reduce(Integer::sum)
                .orElse(0);

        if (stock <= 0) {
            throw new OrangeException("库存不能低于0");
        }

        return ProductResultDto.builder()
                .minPrice(minPrice)
                .minOtPrice(minOtPrice)
                .minCost(minCost)
                .stock(stock)
                .build();
    }

    /**
     * mapTobean
     * @param listMap listMap
     * @return list
     */
    private List<ProductFormatDto> ListMapToListBean(List<Map<String, Object>> listMap) {
        List<ProductFormatDto> list = new ArrayList<>();
        // 循环遍历出map对象
        for (Map<String, Object> m : listMap) {
            list.add(BeanUtil.mapToBean(m, ProductFormatDto.class, true));
        }
        return list;
    }

    /**
     * 增加表头
     * @param headerMap headerMap
     * @param headerMapList headerMapList
     * @param align align
     */
    private void addMap(Map<String, Object> headerMap, List<Map<String, Object>> headerMapList, String align) {
        headerMap.put("title", "图片");
        headerMap.put("slot", "pic");
        headerMap.put("align", align);
        headerMap.put("minWidth", 80);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "售价");
        headerMap.put("slot", "price");
        headerMap.put("align", align);
        headerMap.put("minWidth", 120);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "成本价");
        headerMap.put("slot", "cost");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "原价");
        headerMap.put("slot", "ot_price");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "库存");
        headerMap.put("slot", "stock");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "产品编号");
        headerMap.put("slot", "bar_code");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "重量(KG)");
        headerMap.put("slot", "weight");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "体积(m³)");
        headerMap.put("slot", "volume");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "操作");
        headerMap.put("slot", "action");
        headerMap.put("align", align);
        headerMap.put("minWidth", 70);
        headerMapList.add(ObjectUtil.clone(headerMap));
    }

    /**
     * 组合规则属性算法
     * @param fromatDetailDTOList
     * @return DetailDto
     */
    private DetailDto attrFormat(List<FromatDetailDto> fromatDetailDTOList) {

        List<String> data = new ArrayList<>();
        List<Map<String, Map<String, String>>> res = new ArrayList<>();

        fromatDetailDTOList.stream()
                .map(FromatDetailDto::getDetail)
                .forEach(i -> {
                    if (i == null || i.isEmpty()) {
                        throw new OrangeException("请至少添加一个规格值哦");
                    }
                    String str = ArrayUtil.join(i.toArray(), ",");
                    if (str.contains("-")) {
                        throw new OrangeException("规格值里包含'-',请重新添加");
                    }
                });

        if (fromatDetailDTOList.size() > 1) {
            for (int i = 0; i < fromatDetailDTOList.size() - 1; i++) {
                if (i == 0) {
                    data = fromatDetailDTOList.get(i).getDetail();
                }
                List<String> tmp = new LinkedList<>();
                for (String v : data) {
                    for (String g : fromatDetailDTOList.get(i + 1).getDetail()) {
                        String rep2 = "";
                        if (i == 0) {
                            rep2 = fromatDetailDTOList.get(i).getValue() + "_" + v + "-"
                                    + fromatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        } else {
                            rep2 = v + "-"
                                    + fromatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        }

                        tmp.add(rep2);

                        if (i == fromatDetailDTOList.size() - 2) {
                            Map<String, Map<String, String>> rep4 = new LinkedHashMap<>();
                            Map<String, String> reptemp = new LinkedHashMap<>();
                            for (String h : Arrays.asList(rep2.split("-"))) {
                                List<String> rep3 = Arrays.asList(h.split("_"));
                                if (rep3.size() > 1) {
                                    reptemp.put(rep3.get(0), rep3.get(1));
                                } else {
                                    reptemp.put(rep3.get(0), "");
                                }
                            }
                            rep4.put("detail", reptemp);

                            res.add(rep4);
                        }
                    }

                }

                if (!tmp.isEmpty()) {
                    data = tmp;
                }
            }
        } else {
            List<String> dataArr = new ArrayList<>();
            for (FromatDetailDto fromatDetailDTO : fromatDetailDTOList) {
                for (String str : fromatDetailDTO.getDetail()) {
                    Map<String, Map<String, String>> map2 = new LinkedHashMap<>();
                    dataArr.add(fromatDetailDTO.getValue() + "_" + str);
                    Map<String, String> map1 = new LinkedHashMap<>();
                    map1.put(fromatDetailDTO.getValue(), str);
                    map2.put("detail", map1);
                    res.add(map2);
                }
            }
            String s = StrUtil.join("-", dataArr);
            data.add(s);
        }

        DetailDto detailDto = new DetailDto();
        detailDto.setData(data);
        detailDto.setRes(res);

        return detailDto;
    }

}
